5. Histogram & Boxplot 函数¶

5.1 直方图 Histogram¶

使用go.Histogram()函数可以绘制直方图(用以观察数据分布的形态,了解数据的取值范围)。
若将数据赋值给函数的x变量,即可绘制直方图;若将数据赋值给函数的y变量,则绘制水平直方图。其它常用参数如下:

  • histnorm:设置纵坐标显示格式,可选参数有“”/ percent/ probability/ density/ probability density。默认情况下,表示纵坐标显示每个区间内的样本数量;若为percent或probability,表示纵坐标显示每个区间内的样本频率(即样本占总体的百分比);若为density,则每个小矩形的面积为所在范围内的样本数量,所有矩形面积相加为样本总数;若为probability density,则每个小矩形的面积为所在范围内的样本占总体的比例,所有面积数值相加为1。
  • orientation:设置图形的方向,v表示垂直显示,h表示水平显示。
  • cumulative:累积直方图参数。enabled是布尔型,设置为True会显示累积直方图,默认不对频率或频数进行累积;direction用于设置累积方向,确定频率是从1-0降序还是0-1升序。
  • autobinx:布尔型,是否自动划分区间。
  • nbinsx:整形,最大显示区间数目。
  • xbins:设置划分区间属性,有start、end、size三个关键字,分别设置起始坐标、终止坐标和区间长度。
In [1]:
# 5-1 Basic Histogram 基本直方图
import plotly.graph_objects as go
import numpy as np

x = np.random.randn(500)

fig = go.Figure(data = go.Histogram(
    # 若是y = x,则绘制水平直方图,称为 Horizontal Histogram
    x = x,
    # histnorm:设置纵坐标显示格式,probability/percent表示落入区间内的样本频率,称为 Normalized Histogram
    histnorm = 'probability',
))

fig.show()

如果要观察两组数据的分布情况,Plotly默认会将两个直方图的柱形宽度强制变窄,可以在Layout中设置barmode属性:

  • 默认会以group形式显示;
  • 若设置为overlay,则绘制出重叠直方图 Overlaid Histogram;
  • 若设置为stack,则绘制出层叠直方图 Stacked Histograms。
In [2]:
# 5-2 Overlaid & Stacked Histogram 重叠&层叠直方图
import plotly.graph_objects as go
import numpy as np

x0 = np.random.randn(500)
x1 = np.random.randn(500) + 2

fig = go.Figure()
fig.add_trace(go.Histogram(x = x0))
fig.add_trace(go.Histogram(x = x1))

fig.update_layout(barmode = 'overlay')  # 绘制 Overlaid Histogram 重叠直方图
# fig.update_layout(barmode = 'stack')  # 绘制 Stacked Histograms 层叠直方图

fig.update_traces(opacity = 0.75)  # 一般绘制重叠直方图时建议将不透明度降低

fig.show()
In [3]:
# 5-3 Styled Histogram 风格化直方图
import plotly.graph_objects as go

import numpy as np
x0 = np.random.randn(500)
x1 = np.random.randn(500) + 2

fig = go.Figure()

fig.add_trace(go.Histogram(
    x = x0,
    histnorm = 'percent',
    name = 'control',  # name用于图例legend和交互显示
    xbins = dict(  # xbins用于设置分布区间
        start = -3.0,
        end = 3.0,
        size = 0.5
    ),
    marker = dict(color = '#EB89B5'),
    opacity = 0.75
))

fig.add_trace(go.Histogram(
    x = x1,
    histnorm = 'percent',
    name = 'experimental',  # name用于图例legend和交互显示
    nbinsx = 15,  # nbinsx用于设置最大区间数量
    marker = dict(color = '#330C73'),
    opacity = 0.75
))

fig.update_layout(
    title_text='Sampled Results',
    xaxis_title_text='Value',
    yaxis_title_text='Count',
    barmode='overlay'
)

fig.show()

练习12. 绘制直方图 Distribution of Orders' Profit¶

导入数据文件'Sample - Superstore.xls',绘制直方图,展示每笔订单的利润(Profit)的分布情况。

In [4]:
# 数据分析:得到每笔订单的利润之和
import pandas as pd
df = pd.read_excel('Sample - Superstore.xls',sheet_name='Orders')
data = df.groupby('Order ID')['Profit'].sum()
data  # 共有5009个订单,远小于记录数
Out[4]:
Order ID
CA-2015-100006    109.6113
CA-2015-100090    -19.0890
CA-2015-100293     31.8696
CA-2015-100328      1.3257
CA-2015-100363      7.7192
                    ...   
US-2018-168802      5.9696
US-2018-169320     16.6721
US-2018-169488     26.5552
US-2018-169502     32.4527
US-2018-169551    -62.2895
Name: Profit, Length: 5009, dtype: float64
In [5]:
data.describe()
Out[5]:
count    5009.000000
mean       57.176487
std       344.937752
min     -6892.374800
25%         2.052500
50%        16.275800
75%        68.686800
max      8762.389100
Name: Profit, dtype: float64
In [6]:
# 绘制直方图
import plotly.graph_objects as go






fig.update_layout(
    title='Distribution of Orders\' Profit',
    xaxis=dict(title='Profit'),
    yaxis=dict(title='Count')
)

fig.show()

练习13. 绘制重叠直方图 Profit Distribution of Chairs and Tables¶

导入数据文件'Sample - Superstore.xls',绘制重叠直方图,比较产品子类别(Sub-Category)为'Chairs'和'Tables'利润(Profit)的分布情况。

In [7]:
# 数据分析:分别得到产品子类别(Sub-Category)为'Chairs'和'Tables'的每一条记录的利润(Profit),不做聚合
import pandas as pd
df = pd.read_excel('Sample - Superstore.xls',sheet_name='Orders')
data1 = df.loc[df['Sub-Category']=='Chairs','Profit']
data2 = df.loc[df['Sub-Category']=='Tables','Profit']
print('Number of \'Chairs\' records: ', data1.shape)
print('Number of \'Tables\' records: ', data2.shape)
Number of 'Chairs' records:  (617,)
Number of 'Tables' records:  (319,)
In [8]:
# 绘制重叠直方图
import plotly.graph_objects as go

5.2 分布图 Distplot¶

plotly.figure_factory包中的create_distplot()函数能够将直方图与核函数估计可视化融合在一起。

使用help()可以查看该函数的参数及其组成部分,包括:

  1. histogram 直方图;
  2. curve 拟合曲线:(a) kernel density estimation 核密度估计(就像直方图那样,KDE曲线对于绘制分布的形状是一个非常有用的工具,会在一个轴上通过高度沿着其它轴将观察的密度编码。绘制 KDE曲线比绘制直方图需要更多的计算:每个观察点首先都被以这个点为中心的正态分布曲线所替代,然后这些替代的曲线进行加和,并计算出在每个点的密度值。最终生成的曲线被归一化,使得曲线下面包围的面积是1。)(b) normal curve标准曲线:将参数分布拟合到数据集,并可视化地评估其与观察数据的对应程度。
  3. rug plot 轴须图(边际毛毯)。
In [9]:
# import plotly.figure_factory as ff
# help(ff.create_distplot)
In [10]:
# 5-4 Basic Distplot 基本分布图
import plotly.figure_factory as ff
import numpy as np

x = np.random.randn(500)

fig = ff.create_distplot(
    #  以下两个参数不可缺省,均以列表的形式进行传递
    hist_data=[x],  # 数据集
    group_labels=['distplot'],  # 数据集的名称
    
    # curve_type参数默认为kde,若将其设置为normal,将形成一条平滑的拟合数据集曲线 
    curve_type='normal',
)

fig.show()
In [11]:
# 5-5 Styled Distplot for Multiple Datasets 风格化的多个分布图
import plotly.figure_factory as ff
import numpy as np

x1 = np.random.randn(200) - 2
x2 = np.random.randn(200)
x3 = np.random.randn(200) + 2

colors = ['#393E46', '#2BCDC1', '#F66095']  # 自定义颜色列表

fig = ff.create_distplot(
    hist_data=[x1, x2, x3],  # 多个数据集写成列表形式
    group_labels=['Group 1', 'Group 2', 'Group 3'],  # 多个数据集的名称写成列表形式
    
    # 自定义bin的大小
    # bin_size=.2,
    bin_size=[0.1,0.25,0.5],
    
    # 自定义显示的颜色
#     colors=colors,
    
    # 自定义Distplot不显示某一部分(默认3个组成部分均显示)
#     show_hist=False,  # 不绘制直方图
#     show_curve=False,  # 不绘制curve曲线
#     show_rug=False,  # 不绘制轴须图
)

fig.show()

练习14. 绘制分布图 Profit Distribution by Segment¶

导入数据文件'Sample - Superstore.xls',绘制分布图,展示2018年不同用户细分(Segment)每笔订单的利润(Profit)分布情况。

In [12]:
# 数据分析:得到不同用户细分(Segment)中,每笔订单的利润(Profit)之和
import pandas as pd
df = pd.read_excel('Sample - Superstore.xls',sheet_name='Orders')
data = df[df['Order Date'].array.year == 2018]
data = data.groupby(['Segment','Order ID'])['Profit'].sum()
data
Out[12]:
Segment      Order ID      
Consumer     CA-2018-100013      12.2162
             CA-2018-100097     302.4705
             CA-2018-100111    1571.7964
             CA-2018-100160      16.9641
             CA-2018-100230      42.3643
                                 ...    
Home Office  US-2018-162558   -1034.8361
             US-2018-163790     282.4405
             US-2018-166037     157.4685
             US-2018-166324     -52.0700
             US-2018-169502      32.4527
Name: Profit, Length: 1687, dtype: float64
In [13]:
# 绘制分布图
import plotly.figure_factory as ff

hist_data = []
group_labels = []
colors = ['#393E46', '#2BCDC1', '#F66095']  # 自定义颜色列表

5.3 箱线图 Boxplot¶

箱线图boxplot(也称为盒须图)是一种针对连续性变量的统计图。箱线图的用法是,配合离散型变量(定性变量)画分组箱线图作比较。如果只有一个连续型变量(定量变量)往往选择直方图去展示其分布,箱线图更有效的使用方法是作比较。箱线图的基本要素包括:

  • 箱子的中间一条线是数据的中位数(Median, $Q2$),代表了样本数据的平均水平;
  • 箱子的底线和上线分别是数据的下四分位数(First Quartile, $Q1$)和上四分位数(Third Quartile, $Q3$),意味着箱子包含50%的数据(四分位距$IQR=Q3-Q1$)。箱子的高度在一定程度上反映数据的波动程度;
  • 箱子的下边缘(Lower Bound)计算公式为$Q1-1.5*IQR$,如果数据集中所有点都大于这个值,那么下边缘就是最小数据点;
  • 箱子的上边缘(Upper Bound)计算公式为$Q3+1.5*IQR$,如果数据集中所有点都小于这个值,那么上边缘就是最大数据点;
  • 任何低于下边缘或高于上边缘的数据点都被视为异常值。

使用go.Box()函数可以绘制箱线图。若将数值赋值给y变量,即可绘制箱线图;若将数值赋值给x变量,则绘制水平箱线图。其它常用参数如下:

  • boxpoints: 设置样本点,默认为outliers,即显示箱线图之外的异常点;若设置为all,则显示所有的样本点;若设置为suspectedoutliers,在显示异常点的基础上,大于4Q3-3Q1或小于4Q1-3Q3的可疑异常点会被突出显示;
  • boxmean:如果设置为True,样本点的平均值也会同时以虚线的形式显示在箱子中;
  • fillcolor:设置箱子的填充颜色;
  • jitter:设置样本点的抖动值;
  • line:设置箱线图的线条风格,包括颜色color、宽度width等;
  • marker:设置箱线图的数据节点风格,包括颜色color、颜色模式colorscale、透明度opacity等;
  • pointpos:设置样本点相对于箱子的位置;
  • width:设置箱子的宽度;
  • whiskerwidth:设置须线(上方和下方的线条)相对于箱子的宽度。
In [14]:
# 5-6 Basic Box Plot 基本箱线图
import plotly.graph_objects as go
import numpy as np

y0 = np.random.randn(50) - 1
y1 = np.random.randn(50) + 1

fig = go.Figure()
fig.add_trace(go.Box(y = y0))
fig.add_trace(go.Box(y = y1))

# 如果将数值赋值给x变量,则绘制水平箱线图
# fig.add_trace(go.Box(x = y0))
# fig.add_trace(go.Box(x = y1))

fig.show()
In [15]:
# 5-7 Styled Box Plot 风格化箱线图
import plotly.graph_objects as go
import numpy as np

y0 = np.random.randn(100) - 1
y1 = np.random.randn(100) + 1

fig = go.Figure()

fig.add_trace(go.Box(
    y = y0,
    
    boxpoints = 'all',  # 显示所有的样本点
    jitter = 0.5,  # 设置样本点的抖动程度(宽度)
    pointpos = -2,  # 设置样本点相对于箱子的位置
    
    # 设置箱线图的数据节点风格(颜色、大小)
    marker = dict(color = 'lightseagreen', size = 3),
    fillcolor = 'white',  # 设置箱子的填充颜色
    
    # 设置箱线图的线条风格(颜色、宽度)
    line = dict(color = 'grey', width = 1),
    
    boxmean = True,  # 设置显示样本平均值
    width = 0.3,  # 设置箱子的宽度
    whiskerwidth = 0.5  # 设置上下线条相对于箱子的宽度
))

fig.add_trace(go.Box(
    y = y1,
))

fig.show()

练习15. 绘制箱线图(同练习14的分布图)¶

导入数据文件'Sample - Superstore.xls',绘制箱线图,展示2018年不同用户细分(Segment)每一步订单的利润(Profit)分布情况。

In [16]:
# 数据分析:得到不同用户细分(Segment)中,每笔订单的利润(Profit)之和
import pandas as pd
df = pd.read_excel('Sample - Superstore.xls',sheet_name='Orders')
data = df[df['Order Date'].array.year == 2018]
data = data.groupby(['Segment','Order ID'])['Profit'].sum()
data
Out[16]:
Segment      Order ID      
Consumer     CA-2018-100013      12.2162
             CA-2018-100097     302.4705
             CA-2018-100111    1571.7964
             CA-2018-100160      16.9641
             CA-2018-100230      42.3643
                                 ...    
Home Office  US-2018-162558   -1034.8361
             US-2018-163790     282.4405
             US-2018-166037     157.4685
             US-2018-166324     -52.0700
             US-2018-169502      32.4527
Name: Profit, Length: 1687, dtype: float64
In [17]:
# 绘制箱线图
import plotly.graph_objects as go
colors = ['#393E46', '#2BCDC1', '#F66095']  # 自定义颜色列表

练习16. 绘制箱线图 Distribution of Profit by Region¶

导入数据文件'Sample - Superstore.xls',绘制箱线图,展示商品'Supplies'在不同区域(Region)每一条记录的利润(Profit)分布情况,并自定义颜色。

In [18]:
# 数据分析:得到'Supplies'这一商品在不同地区的每一条利润记录
import pandas as pd
df = pd.read_excel('Sample - Superstore.xls',sheet_name='Orders',index_col='Row ID')
data = df[df['Sub-Category']=='Supplies']
data.shape
Out[18]:
(190, 20)
In [19]:
# 绘制箱线图
import pandas as pd
import plotly.graph_objects as go

colors = [ '#2BCDC1', '#FFAB40','#F66095','#4FC3F7']  # 自定义颜色列表